import uuid
from typing import BinaryIO, Optional

import oss2

from common.config import settings

_auth = oss2.Auth(settings.OSS_ACCESS_KEY_ID, settings.OSS_ACCESS_KEY_SECRET)
_bucket = oss2.Bucket(_auth, settings.OSS_ENDPOINT, settings.OSS_BUCKET)


class OSSStorage:
	"""OSS 存储实现，与 LocalFileStorage 同接口"""

	async def save(self, file_data: BinaryIO, uuid_str: Optional[str] = None) -> str:
		"""
		上传二进制流到 OSS
		:param file_data: 文件流
		:param uuid_str: 可选 uuid；不传则内部生成
		:return: 文件在 OSS 的相对路径
		"""
		uuid_str = uuid_str or uuid.uuid4().hex
		object_key = f"web/device/PHOTO_{uuid_str}"
		_bucket.put_object(object_key, file_data)
		return object_key

	def get_url(self, relative_path: str) -> str:
		"""
		返回外网直链（私有桶则后续再换签名 URL）
		"""
		return f"https://{settings.OSS_BUCKET}.{settings.OSS_ENDPOINT.replace('https://', '')}/{relative_path}"

	def get_signed_url(self, relative_path: str,
					   expires: int = 900,
					   internal: bool = False) -> str:
		"""
		生成带签名的临时下载/预览地址
		:param relative_path: 文件在 OSS 里的对象键
		:param expires: 有效秒数，默认 15 min
		:param internal: 是否使用内网域名（ECS 同地域），默认False使用公网
		:return: 签名后的 URL
		"""
		# 内网endpoint需要包含-internal，公网则移除-internal
		endpoint = settings.OSS_ENDPOINT if internal else settings.OSS_ENDPOINT.replace('-internal', '')
		bucket = oss2.Bucket(
			_auth, endpoint, settings.OSS_BUCKET
		)
		return bucket.sign_url('GET', relative_path, expires,
							   slash_safe=True)  # 支持中文
